'''Rance Quest POL parser. With help from MrHands and his PropExtractor'''

import os, sys
from Sanae3D.lib.StructReader import StructReader
from Sanae3D.lib.ModelObject import Model3D

class RanceQuest_POL(Model3D):
    
    def __init__(self, obj3D=None, outFile=None, inFile=None):
        
        super(RanceQuest_POL,self).__init__("POL")
        self.obj3D = obj3D
        self.inFile = inFile
        self.outFile = outFile
        self.meshType = 0
        self.uvs = []
        self.uvs2 = []
        
    def read_name(self):
        
        name = []
        char = self.inFile.read_char()
        while char != "\x00":
            name.append(char)
            char = self.inFile.read_char()
        return ''.join(name)
    
    def check_padding(self):
        
        unk = self.inFile.read_long()
        while unk == -1:
            unk = self.inFile.read_long()
        return unk
    
    def parse_vertices(self, numVerts, meshName):
        
        if self.meshType == 1:
            for i in xrange(numVerts):
                vx, vy, vz = self.inFile.read_float(3)
                unk1, unk2 = self.inFile.read_short(2)
                if unk1 == 1 and unk2 != 0: 
                    self.inFile.read_float()
                else:
                    for j in xrange(unk1):
                        boneIndex = self.inFile.read_long()
                        boneWeight = self.inFile.read_float()
                        
                self.create_vertex(meshName, i)
                self.add_coords(meshName, i, [vx, vy, vz])
            
        elif self.meshType == 2:
        
            for i in xrange(numVerts):
                vx, vy, vz = self.inFile.read_float(3)
                unk1 = self.inFile.read_short()
                for j in xrange(unk1):
                    boneIndex = self.inFile.read_short()
                    boneWeight = self.inFile.read_float()
            
                self.create_vertex(meshName, i)
                self.add_coords(meshName, i, [vx, vy, vz])
            
    def parse_UV(self, numUV, meshName):
        
        for i in xrange(numUV):
            tu, tv = self.inFile.read_float(2)
            self.uvs.append([tu, tv])
            
    def parse_UV2(self, numUV, meshName):
    
        for i in xrange(numUV):
            tu, tv = self.inFile.read_float(2)
            self.uvs2.append([tu, tv])
            
    def parse_faces(self, meshName, numFaces, matNum, unk2):
        
        for j in xrange(numFaces):
            v1, v2, v3 = self.inFile.read_long(3)
            uv1, uv2, uv3 = self.inFile.read_long(3)
            
            if self.uvs2 or unk2:
                uv21, uv22, uv23 = self.inFile.read_long(3)
            self.inFile.read_long(3)
            self.inFile.read_float(9)
            self.inFile.read_long(1)
            
            self.create_face(meshName, j)
            self.add_face_verts(meshName, j, [v1, v2, v3])
            
            u1, v1 = self.uvs[uv1]
            u2, v2 = self.uvs[uv2]
            u3, v3 = self.uvs[uv3]
            uv = [u1, v1, u2, v2, u3, v3]
            self.add_face_uv(meshName, j, uv)
            self.add_face_material(meshName, j, matNum)
            
    def parse_unk(self, count, meshName):
        
        if self.meshType == 1:
            self.inFile.seek(count*12, 1)
        elif self.meshType == 2:
            self.inFile.seek(count*4, 1)
                
    def parse_unk2(self, count, meshName):
        
        self.inFile.seek(count, 1)
                    
    def parse_meshes(self, numMesh):
        
        for i in xrange(numMesh):
            self.uvs = []
            self.uvs2 = []
            
            meshName = self.read_name()
            
            self.create_object(meshName)
            matNum = self.inFile.read_long()
            print meshName, matNum
            
            numVerts = self.inFile.read_long()
            self.parse_vertices(numVerts, meshName)
            
            numUV = self.inFile.read_long()
            self.parse_UV(numUV, meshName)
            
            numUV2 = self.inFile.read_long()
            self.parse_UV2(numUV2, meshName)
            
            numUnk = self.inFile.read_long()
            self.parse_unk(numUnk, meshName)
            
            numUnk2 = 0
            if self.meshType == 2:
                numUnk2 = self.inFile.read_long()
                self.parse_unk2(numUnk2, meshName)
            
            numFaces = self.inFile.read_long()
            self.parse_faces(meshName, numFaces, matNum, numUnk2)
            
            if self.meshType == 1:
                self.inFile.seek(8, 1)
            numBones = self.check_padding()
            if numBones > 0:
                break
        
        self.parse_bones(numBones)
            
    def parse_bones(self, numBones):
        
        for i in xrange(numBones):
            boneName = self.read_name()
            unk1, unk2 = self.inFile.read_long(2)
            self.inFile.read_float(7)
        
    def parse_submaterials(self, numMat):
        
        for i in xrange(numMat):
            matName = self.read_name()
            matNum = self.mat_count()
            #self.create_material(matNum)
            #self.add_material_name(matNum, matName)
            index = self.inFile.read_ulong()
            if index == 1:
                texName = self.read_name()
                unk2  = self.inFile.read_long()
            elif index == 2:
                texName = self.read_name()
                unk2 = self.inFile.read_long(2)
                texName2 = self.read_name()
                unk3 = self.inFile.read_long()
                
            #self.add_texture_name(matNum, texName + ".tga")
            print "--", matName, texName
        
    def parse_materials(self, numMat):
        
        for i in xrange(numMat):
            matName = self.read_name()
            matNum = self.mat_count()
            self.create_material(matNum)
            self.add_material_name(matNum, matName)
            index = self.inFile.read_ulong()
            
            if index == 0:
                #submaterials
                print matName
                numSubMat = self.inFile.read_ulong()
                self.parse_submaterials(numSubMat)
            else:
                if index == 1:
                    texName = self.read_name()
                    unk2, unk3 = self.inFile.read_long(2)
                    print matName, texName
                elif index == 2:
                    texName = self.read_name()
                    unk2 = self.inFile.read_long()
                    texName2 = self.read_name()
                    unk3 = self.inFile.read_long(2)
                    print matName, texName
                elif index == 3:
                    texName = self.read_name()
                    unk2 = self.inFile.read_long()
                    specName = self.read_name()
                    self.inFile.read_long(2)
                    normName = self.read_name()
                    self.inFile.read_long(2)
                self.add_texture_name(matNum, texName + ".tga")
            
            
    def parse_file(self):
        '''Main parser method. Can be replaced'''
        
        idstring = self.inFile.read_string(4)
        self.meshType = self.inFile.read_ulong()
        numMat = self.inFile.read_ulong()        
        self.parse_materials(numMat)
        
        numMesh = self.inFile.read_ulong()
        self.check_padding()
        print("%s mesh" %numMesh)
        self.parse_meshes(numMesh)
        
        
def read_file(path):
    '''Read the file'''
    
    openFile = StructReader(open(path, 'rb'))
    obj = RanceQuest_POL(inFile=openFile)
    obj.parse_file()
    openFile.close()
    return obj

def write_file(path):
    
    pass

def definitions():
    '''Return the header, extension, and a description of the format'''
    
    return "POL", "POL", ""

if __name__ == '__main__':
    
    file1 = "point.pol"
    file2 = "monsutar.pol"
    obj = read_file(file2)